package com.zhucan.account.application.command.impl;

import com.zhucan.account.application.command.AccountCommandService;
import com.zhucan.account.application.command.assembler.AccountCreateCommandAssembler;
import com.zhucan.account.application.command.cmd.*;
import com.zhucan.account.domain.aggregate.Account;
import com.zhucan.account.domain.repository.AccountStorage;
import com.zhucan.account.domain.service.AccountService;
import com.zhucan.account.infrastructure.amqp.AccountDomainEventPublisher;
import com.zhucan.account.infrastructure.amqp.event.AccountNoticeEvent;
import com.zhucan.account.infrastructure.email.event.EmailNoticeEvent;
import lombok.AllArgsConstructor;
import org.mapstruct.factory.Mappers;
import org.springframework.stereotype.Service;

/**
 * author: zhuCan
 * date: 2020/8/4 19:55
 * description:
 */
@Service
@AllArgsConstructor
public class AccountCommandServiceImpl implements AccountCommandService {

    // 仓储
    private AccountStorage storage;

    // 领域服务
    private AccountService accountService;

    // 领域事件发布者
    private AccountDomainEventPublisher domainEventPublisher;

    @Override
    public void createAccount(AccountCreateCommand createCommand) {
        // 检查身份证是否已注册
        accountService.checkIdentityCard(createCommand.getIdentityCard());

        AccountCreateCommandAssembler assembler = Mappers.getMapper(AccountCreateCommandAssembler.class);

        Account account = new Account(assembler.convertEntity(createCommand));
        account.createAccount();

        storage.save(account);
        // 发布领域事件
        domainEventPublisher.publish(account.getIdentityCard(), new EmailNoticeEvent("账户创建成功"));
    }

    @Override
    public void setPassword(Long id, AccountPasswordChangeCommand changeCommand) {
        Account account = storage.load(id);
        account.setPassword(changeCommand.getPassword());

        storage.save(account);
    }

    @Override
    public void suspendAccount(Long id) {
        // 加载领域对象
        Account account = storage.load(id);
        account.suspend();

        // 持久化领域对象
        storage.save(account);
        // 发送领域事件
        domainEventPublisher.publish(id, new AccountNoticeEvent("账户已被冻结"));
    }

    @Override
    public void deposit(Long id, AccountDepositCommand depositCommand) {
        Account account = storage.load(id);
        account.deposit(depositCommand.getAmount());

        storage.save(account);
    }

    @Override
    public void withdraw(Long id, AccountWithdrawCommand withdrawCommand) {
        Account account = storage.load(id);
        account.withdraw(withdrawCommand.getAmount());

        storage.save(account);
    }

    @Override
    public void transfer(Long id, Long targetId, AccountTransferCommand transferCommand) {
        // 领域服务执行转账
        accountService.transfer(id, targetId, transferCommand);

        // 发送领域事件
        domainEventPublisher.publish(targetId, new AccountNoticeEvent("转账已到账"));
    }
}
